home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’96
/
FinderFlocks
/
FlockUtils.cp
< prev
next >
Wrap
Text File
|
1996-06-22
|
14KB
|
559 lines
#include "CFlock.h"
#include "FlockDrawing.h"
#include <stdio.h>
// a sick hack for key control of the flock
extern ControlRec gCurrentControls;
extern Boolean gControlsChanged;
short
abs(short i)
{
if (i < 0)
return(-i);
return(i);
}
/* long
labs(long i)
{
if (i < 0)
return(-i);
return(i);
} */
/* This routine replaces the given string with a string from the resource file, and also
returns it */
/* char* TheStr(Str255 str, short index)
{
GetIndString(str, kFlockStringsID, index);
return &str;
} */
// This routine averages the two vectors, and returns the result in a
void TwoVecAvg(FloatPoint *a, FloatPoint *b)
{
a->h = (a->h + b->h) / 2;
a->v = (a->v + b->v) / 2;
}
double VecMagSq(double h, double v)
{
double hsq, vsq;
hsq = h * h;
vsq = v * v;
return (hsq + vsq);
}
void Clamp(FloatPoint *vec, double max)
{
double theMax = max;
double biggest;
double absh, absv;
absh = fabs(vec->h);
absv = fabs(vec->v);
biggest = (absv > absh) ? absv : absh;
if(biggest <= max)
return;
vec->h = (vec->h * max) / biggest;
vec->v = (vec->v * max) / biggest;
}
/* Some QuickDraw Utils */
// This routine builds a new PixMap or Bitmap to the given specs. It simply clones
// the current GDevice's PixMap, then resizes it. It does NOT allocate space for
// the image itself, but returns the required size in bytes. Returns nil on error.
// Assumes that the current device is the right one
long BuildMap(Handle *aMap, Rect *aRect, short theDepth)
{
long rowbytes, bitsSize;
Handle localMap;
// If theDepth is 1, then we have either B&W QD or ColorQD in 1 bit.
// In either case use a BitMap, not a PixMap.
if(theDepth == 1)
{
// Allocate space for the BitMap
localMap = NewHandle(sizeof(BitMap));
if(localMap == nil)
return 0;
// Resize the new map to the rect
bitsSize = SizeBitMap((BitMap *)*localMap, aRect);
}
else // a full-fledged PixMap, Color QD better be available...
{
GDHandle mapDevice;
// Get the current device
mapDevice = GetGDevice();
if(mapDevice == nil)
return 0;
// Allocate space for the PixMap
localMap = (Handle)NewPixMap();
if(localMap == nil)
return 0;
// Clone the device's PixMap, including color table
CopyPixMap((*mapDevice)->gdPMap, (PixMapHandle)localMap);
// Resize the new map to the rect
bitsSize = SizePixMap((PixMapHandle)localMap, aRect);
}
// Cool, we made it. Install the new map and return size of image
*aMap = localMap;
return bitsSize;
}
// Changes rowBytes and bounds of the given PixMap so that it corresponds to the given rect
long SizePixMap(PixMapHandle ThePix, Rect *TheRect)
{
long rb, ptrsize;
rb = ((((**ThePix).pixelSize * (TheRect->right - TheRect->left)) + 15) / 16) * 2;
ptrsize = rb * (TheRect->bottom - TheRect->top);
(**ThePix).rowBytes = rb | 0x8000;
(**ThePix).bounds = *TheRect;
return ptrsize;
}
// Changes rowBytes and bounds of the given BitMap so that it corresponds to the given rect
long SizeBitMap(BitMap *TheMap, Rect *TheRect)
{
long rb, ptrsize;
rb = ((TheRect->right - TheRect->left + 15) / 16) * 2;
ptrsize = rb * (TheRect->bottom - TheRect->top);
TheMap->rowBytes = rb;
TheMap->bounds = *TheRect;
return ptrsize;
}
// A key was hit: if it's a flock control do something
/*
0x1E, // up and down arrows : flock size
0x1F,
0x1C, // left and right arrows: flock type
0x1D,
0x31, // 1, q: comfy distance
0x71,
0x32, // 2, w: vision limit
0x77,
0x34, // 4, r: Max Avoid Urge
0x72,
0x35, // 5, t: Max match Urge
0x74,
0x36, // 6, y: Max Centering Urge
0x79,
0x38, // 8, i: max Oomph
0x69,
0x39, // 9, o: Max Accel
0x6F,
0x30, // 0, p: Max Velocity
0x70,
*/
void FlockControlKey(char key)
{
switch(key)
{
// up and down arrows affect flock size
case 0x1E:
//gCurrentControls.fNumBoidsCtl += 10;
gControlsChanged = true;
break;
case 0x1F:
//gCurrentControls.fNumBoidsCtl -= 10;
gControlsChanged = true;
break;
// left and right arrows affect flock type
case 0x1C:
gCurrentControls.fBoidTypeCtl -= 1;
gControlsChanged = true;
break;
case 0x1D:
gCurrentControls.fBoidTypeCtl += 1;
gControlsChanged = true;
break;
// 1 and q affect comfy dist
case 0x31:
gCurrentControls.fComfyDistCtl += 1;
gControlsChanged = true;
break;
case 0x71:
gCurrentControls.fComfyDistCtl -= 1;
gControlsChanged = true;
break;
// 2 and w affect vision limit
case 0x32:
gCurrentControls.fAwareDistCtl += 1;
gControlsChanged = true;
break;
case 0x77:
gCurrentControls.fAwareDistCtl -= 1;
gControlsChanged = true;
break;
// 4 and r affect max avoidance urge
case 0x34:
gCurrentControls.fAvoidMaxCtl += 1;
gControlsChanged = true;
break;
case 0x72:
gCurrentControls.fAvoidMaxCtl -= 1;
gControlsChanged = true;
break;
// 5 and t affect max matching urge
case 0x35:
gCurrentControls.fMatchMaxCtl += 1;
gControlsChanged = true;
break;
case 0x74:
gCurrentControls.fMatchMaxCtl -= 1;
gControlsChanged = true;
break;
// 6 and y affect max centering urge
case 0x36:
gCurrentControls.fCenterMaxCtl += 1;
gControlsChanged = true;
break;
case 0x79:
gCurrentControls.fCenterMaxCtl -= 1;
gControlsChanged = true;
break;
// 8 and i affect max oomph available
case 0x38:
gCurrentControls.fMaxEffortCtl += 1;
gControlsChanged = true;
break;
case 0x69:
gCurrentControls.fMaxEffortCtl -= 1;
gControlsChanged = true;
break;
// 9 and o affect max acceleration
case 0x39:
gCurrentControls.fMaxAccelCtl += 1;
gControlsChanged = true;
break;
case 0x6F:
gCurrentControls.fMaxAccelCtl -= 1;
gControlsChanged = true;
break;
// 0 and p affect max velocity
case 0x30:
gCurrentControls.fMaxVelocityCtl += 1;
gControlsChanged = true;
break;
case 0x70:
gCurrentControls.fMaxVelocityCtl -= 1;
gControlsChanged = true;
break;
}
}
/* Sets the given control block to the values in the appropriate resource, but
preserves fNumBoidsCtl and fBoidTypeCtl */
void GetNewControls(ControlRec *controls, long type)
{
Handle hVals = nil;
short num1, num2;
num1 = controls->fNumBoidsCtl;
num2 = controls->fBoidTypeCtl;
/* Get the default control values */
hVals = GetResource('FCTL', type + kIDOffset);
if(hVals != nil)
{
ShortControlRec shorts;
shorts = *(ShortControlRec *)(*hVals);
// convert to internal longs and doubles
controls->fNumBoidsCtl = shorts.fNumBoidsCtl;
controls->fBoidTypeCtl = shorts.fBoidTypeCtl;
controls->fComfyDistCtl = shorts.fComfyDistCtl;
controls->fAwareDistCtl = shorts.fAwareDistCtl;
controls->fAvoidMaxCtl = shorts.fAvoidMaxCtl;
controls->fMatchMaxCtl = shorts.fMatchMaxCtl;
controls->fCenterMaxCtl = shorts.fCenterMaxCtl;
controls->fMaxEffortCtl = shorts.fMaxEffortCtl;
controls->fMaxAccelCtl = shorts.fMaxAccelCtl;
controls->fMaxVelocityCtl = shorts.fMaxVelocityCtl;
ReleaseResource(hVals);
}
else
{
/* Fake it */
controls->fNumBoidsCtl = 10;
controls->fBoidTypeCtl = 1;
controls->fComfyDistCtl = 50;
controls->fAwareDistCtl = 50;
controls->fAvoidMaxCtl = 50;
controls->fMatchMaxCtl = 50;
controls->fCenterMaxCtl = 50;
controls->fMaxEffortCtl = 50;
controls->fMaxAccelCtl = 50;
controls->fMaxVelocityCtl = 50;
}
controls->fNumBoidsCtl = num1;
controls->fBoidTypeCtl = num2;
}
/* turns the given raw (0-100) control block into good controls */
/*void ProcessControls(ControlRec *raw, ControlRec *good)
{
*good = *raw;
good->fComfyDistCtl *= 4;
good->fAwareDistCtl *= 8;
good->fAvoidMaxCtl /= 4;
good->fMatchMaxCtl /= 4;
good->fCenterMaxCtl /= 8;
good->fMaxEffortCtl *= 1;
good->fMaxAccelCtl /= 4;
good->fMaxVelocityCtl /= 4;
good->fNumBoidsCtl *= 10;
if(good->fNumBoidsCtl > kMaxBoids)
good->fNumBoidsCtl = kMaxBoids;
}*/
/*void SaveControls(ControlRec *controls, long type)
{
Handle contrRes;
ShortControlRec shorts;
// Save the controls for next time. First get the default control values
contrRes = GetResource('FCTL', type + kIDOffset);
if(contrRes == nil) // No resource, make one
{
contrRes = NewHandle(sizeof(ShortControlRec));
if(contrRes == nil) // Bummer, not enough memory. So it goes...
return;
// Make it a resource
AddResource(contrRes, 'FCTL', type + kIDOffset, "\p");
if(ResError() != noErr)
{
DisposHandle(contrRes);
return;
}
}
// Copy the controls
shorts.fNumBoidsCtl = controls->fNumBoidsCtl;
shorts.fBoidTypeCtl = controls->fBoidTypeCtl;
shorts.fComfyDistCtl = controls->fComfyDistCtl;
shorts.fAwareDistCtl = controls->fAwareDistCtl;
shorts.fAvoidMaxCtl = controls->fAvoidMaxCtl;
shorts.fMatchMaxCtl = controls->fMatchMaxCtl;
shorts.fCenterMaxCtl = controls->fCenterMaxCtl;
shorts.fMaxEffortCtl = controls->fMaxEffortCtl;
shorts.fMaxAccelCtl = controls->fMaxAccelCtl;
shorts.fMaxVelocityCtl = controls->fMaxVelocityCtl;
*(ShortControlRec *)*contrRes = shorts;
ChangedResource(contrRes); // make sure it gets written out
if(ResError() == noErr)
WriteResource(contrRes); // ignore the potential write error
ReleaseResource(contrRes);
}*/
/*void GetFlockRect(RgnHandle blankRgn, GMParamBlockPtr params,
Rect *flockRect, long *depth, long screenSetting)
{
Rect deepRect, bigRect, blankRect;
short cnt, numMonitors, deepDepth = 0, bigDepth = 0;
long deepArea = 0, bigArea = 0;
blankRect = (**blankRgn).rgnBBox;
//Look at all monitors, then pick which one to use.
numMonitors = params->monitors->monitorCount;
for(cnt = 0; cnt < numMonitors; cnt++)
{
Rect thisRect;
long thisArea;
short thisDepth;
thisRect = params->monitors->monitorList[cnt].bounds;
// If this monitor intersects the blankRgn, log its depth and area of intersection
if(SectRect(&thisRect, &blankRect, &thisRect))
{
thisArea = (long)(thisRect.right - thisRect.left) *
(long)(thisRect.bottom - thisRect.top);
thisDepth = params->monitors->monitorList[cnt].curDepth;
// log results if they supersede earlier ones
if(thisDepth > deepDepth)
{
deepArea = thisArea; //Log if deeper than the others
deepDepth = thisDepth;
deepRect = thisRect;
}
if(thisArea > bigArea) //Log if larger than the others
{
bigArea = thisArea;
bigDepth = thisDepth;
bigRect = thisRect;
}
}
}
//Logged all monitors. Now pick the right one
if( screenSetting == kAllScr)
{
*depth = bigDepth;
*flockRect = (**blankRgn).rgnBBox;
}
else if(screenSetting == kBigScr)
{
*depth = bigDepth;
*flockRect = bigRect;
}
else // use deepest
{
if(deepDepth == bigDepth)
{
*depth = bigDepth;
*flockRect = bigRect;
}
else
{
*depth = deepDepth;
*flockRect = deepRect;
}
}
} */
void DrawControlValues(Rect *screenRect)
{
char textBuffer[512];
long length;
RGBColor theTextColor = {65535, 0, 0}, blackish = {0, 0, 0}, savedColor;
short theXPos = 10, theYPos = screenRect->bottom - 160; // (10 controls * 15 pixel line height) + 10 slop
Rect invalRect;
// Save the current color
GetForeColor( &savedColor );
// set up the invalid rect
invalRect = *screenRect;
invalRect.right = 250;
invalRect.top = theYPos - 15;
RGBForeColor( &blackish );
PaintRect(&invalRect);
RGBForeColor( &theTextColor );
// Draw each control's value
length = sprintf((char *)&textBuffer[1],
"%ld - Number of boids",
gCurrentControls.fNumBoidsCtl);
textBuffer[0] = length;
MoveTo(theXPos, theYPos );
DrawString((ConstStr255Param)textBuffer);
theYPos += 15;
length = sprintf((char *)&textBuffer[1],
"%ld - Boid type",
gCurrentControls.fBoidTypeCtl);
textBuffer[0] = length;
MoveTo(theXPos, theYPos );
DrawString((ConstStr255Param)textBuffer);
theYPos += 15;
length = sprintf((char *)&textBuffer[1],
"%.2lf - Comfy distance",
gCurrentControls.fComfyDistCtl);
textBuffer[0] = length;
MoveTo(theXPos, theYPos );
DrawString((ConstStr255Param)textBuffer);
theYPos += 15;
length = sprintf((char *)&textBuffer[1],
"%.2lf - Aware distance",
gCurrentControls.fAwareDistCtl);
textBuffer[0] = length;
MoveTo(theXPos, theYPos );
DrawString((ConstStr255Param)textBuffer);
theYPos += 15;
length = sprintf((char *)&textBuffer[1],
"%.2lf - Max. Avoidance",
gCurrentControls.fAvoidMaxCtl);
textBuffer[0] = length;
MoveTo(theXPos, theYPos );
DrawString((ConstStr255Param)textBuffer);
theYPos += 15;
length = sprintf((char *)&textBuffer[1],
"%.2lf - Max. Match",
gCurrentControls.fMatchMaxCtl);
textBuffer[0] = length;
MoveTo(theXPos, theYPos );
DrawString((ConstStr255Param)textBuffer);
theYPos += 15;
length = sprintf((char *)&textBuffer[1],
"%.2lf - Max. Centering",
gCurrentControls.fCenterMaxCtl);
textBuffer[0] = length;
MoveTo(theXPos, theYPos );
DrawString((ConstStr255Param)textBuffer);
theYPos += 15;
length = sprintf((char *)&textBuffer[1],
"%.2lf - Max. Oomph",
gCurrentControls.fMaxEffortCtl);
textBuffer[0] = length;
MoveTo(theXPos, theYPos );
DrawString((ConstStr255Param)textBuffer);
theYPos += 15;
length = sprintf((char *)&textBuffer[1],
"%.2lf - Max. Acceleration",
gCurrentControls.fMaxAccelCtl);
textBuffer[0] = length;
MoveTo(theXPos, theYPos );
DrawString((ConstStr255Param)textBuffer);
theYPos += 15;
length = sprintf((char *)&textBuffer[1],
"%.2lf - Max. Velocity",
gCurrentControls.fMaxVelocityCtl);
textBuffer[0] = length;
MoveTo(theXPos, theYPos );
DrawString((ConstStr255Param)textBuffer);
// Invalidate the rect so it wil draw
MarkRect(&invalRect);
// Restore the color
RGBForeColor( &savedColor );
}